﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using UnityEngine;
using UnityEditor;

// 文件夹打包方式
public enum FloderPackType
{
    None,           // 不处理该文件夹
    Copy,           // 直接将文件夹拷贝到目标目录
    BundleTogether, // 将文件夹打包到一个AssetBundle
    BundleEachFile, // 每个文件打包成一个AssetBundle
}

// 文件打包方式
public enum FilePackType
{
    UseFloderPack,  // 使用文件夹设定的打包方式
    None,           // 不处理
    Copy,           // 直接复制到目标目录
    Bundle,         // 打包成AssetBundle
}

// 文件夹打包
[Serializable]
public class FloderPack
{
    public string guid;
    public FloderPackType type;
    public string filter;
    public string extension;
    public bool onlyPackerUsed;
    public bool packerDependencies;
    public FloderPack(string guid, FloderPackType type, string filter, string extension,bool onlyPackerUsed = false,bool packerDependencies = false)
    {
        this.guid = guid;
        this.type = type;
        this.filter = filter;
        this.extension = extension;
        this.onlyPackerUsed = onlyPackerUsed;
        this.packerDependencies = packerDependencies;
    }
}

// 文件打包
[Serializable]
public class FilePack
{
    public string guid;
    public FilePackType type;

    public FilePack(string guid, FilePackType type)
    {
        this.guid = guid;
        this.type = type;
    }
}

public class PackerSetting : ScriptableObject
{
    [MenuItem("Assets/Create/PackerSetting")]
    public static void CreateAsset()
    {
        EditorHelper.CreateAsset<PackerSetting>();
    }

    #region 打包配置
    public string rootPath
    {
        get { return LoadManager.rootPath; }
    }
    public static string outputPath
    {
        get {
            return LoadManager.outputPath;
        }
    }

    [HideInInspector]
    public List<FloderPack> floderPacks = new List<FloderPack>();
    [HideInInspector]
    public List<FilePack> filePacks = new List<FilePack>();

    public FloderPack GetFloderPack(string guid)
    {
        foreach (var item in floderPacks)
        {
            if (string.Equals(item.guid, guid))
                return item;
        }
        return null;
    }

    public FloderPackType GetFloderPackType(string guid)
    {
        var pack = GetFloderPack(guid);
        return pack != null ? pack.type : FloderPackType.None;
    }

    public void SetFloderPackType(string guid, FloderPackType type)
    {
        var pack = GetFloderPack(guid);
        if (pack != null)
            pack.type = type;
        else
            floderPacks.Add(new FloderPack(guid, type, string.Empty, string.Empty));

        EditorUtility.SetDirty(this);
    }

    public string GetFloderPackFilter(string guid)
    {
        var pack = GetFloderPack(guid);
        return pack != null ? pack.filter : string.Empty;
    }

    public void SetFloderPackFilter(string guid, string filter)
    {
        var pack = GetFloderPack(guid);
        if (pack != null)
            pack.filter = filter;
        else
            floderPacks.Add(new FloderPack(guid, FloderPackType.None, filter, string.Empty));

        EditorUtility.SetDirty(this);
    }

    public string GetFloderPackExtension(string guid)
    {
        var pack = GetFloderPack(guid);
        return pack != null ? pack.extension : string.Empty;
    }

    public void SetFloderPackExtension(string guid, string extension)
    {
        var pack = GetFloderPack(guid);
        if (pack != null)
            pack.extension = extension;
        else
            floderPacks.Add(new FloderPack(guid, FloderPackType.None, string.Empty, extension));

        EditorUtility.SetDirty(this);
    }
    public bool GetTargetPackOnlyPackerUsed(string guid)
    {
        var pack = GetFloderPack(guid);
        return pack != null ? pack.onlyPackerUsed :false;
    }


    public void SetTargetPackOnlyPackerUsed(string guid, bool res)
    {
        var pack = GetFloderPack(guid);
        if (pack != null)
            pack.onlyPackerUsed = res;
        else
            floderPacks.Add(new FloderPack(guid, FloderPackType.None, string.Empty, string.Empty, res));

        EditorUtility.SetDirty(this);
    }
    public bool GetTargetPackpackerDependencies(string guid)
    {
        var pack = GetFloderPack(guid);
        return pack != null ? pack.packerDependencies : false;
    }

    public void SetTargetPackpackerDependencies(string guid, bool res)
    {
        var pack = GetFloderPack(guid);
        if (pack != null)
            pack.packerDependencies = res;
        else
            floderPacks.Add(new FloderPack(guid, FloderPackType.None, string.Empty, string.Empty, false, res));

        EditorUtility.SetDirty(this);
    }
    
    public FilePack GetFilePack(string guid)
    {
        foreach (var item in filePacks)
        {
            if (string.Equals(item.guid, guid))
                return item;
        }
        return null;
    }

    public FilePackType GetFilePackType(string guid)
    {
        var pack = GetFilePack(guid);
        return pack != null ? pack.type : FilePackType.UseFloderPack;
    }

    public void SetFilePackType(string guid, FilePackType type)
    {
        var pack = GetFilePack(guid);
        if (pack != null)
            pack.type = type;
        else
            filePacks.Add(new FilePack(guid, type));

        EditorUtility.SetDirty(this);
    }
    #endregion

    #region 打包方法
    /// <summary>
    /// 打包所有资源
    /// </summary>
    public void BuildAll(bool rebuild, bool encryptLua)
    {
        if (rebuild)
        {
           Directory.Delete(outputPath, true);
           // Directory.Delete("Assets/StreamingAssets/data", true);
        }

        var asset2Pack = new Dictionary<string, string>();
        var asset2Dependency = new Dictionary<string, int>();
        Queue<string> dependencyQueue = new Queue<string>();

        // 在需要打包的文件夹中搜索Asset
        foreach (var item in floderPacks)
        {
            if (item.type == FloderPackType.None)
                continue;
            var path = AssetDatabase.GUIDToAssetPath(item.guid);
            if (String.IsNullOrEmpty(path))
                continue;

            var assetPathes = FindAssets(path, item);
            foreach (var assetPath in assetPathes)
            {
                UnityEngine.Debug.Log(assetPath + " " + path + " " + item.packerDependencies);
                string path2;
                if (asset2Pack.TryGetValue(assetPath, out path2))
                {
                    // 该asset的打包配置已经存在，优先使用子目录的打包配置
                    if (path.Length > path2.Length)
                        asset2Pack[assetPath] = path;
                }
                else
                {
                    asset2Pack.Add(assetPath, path);
                }
            }
        }

        // 遍历需要打包的文件
        foreach (var item in filePacks)
        {
            if (item.type == FilePackType.UseFloderPack)
                continue;

            var assetPath = AssetDatabase.GUIDToAssetPath(item.guid);
            if (item.type == FilePackType.None)
            {
                asset2Pack.Remove(assetPath);
                continue;
            }

            asset2Pack[assetPath] = assetPath;
        }

        //广度优先遍历依赖
        foreach(var item in asset2Pack)
        {
            AddDep(asset2Pack, asset2Dependency, dependencyQueue, item.Key);
        }
        while(dependencyQueue.Count > 0)
        {
            string dependencyPath = dependencyQueue.Dequeue();
            AddDep(asset2Pack, asset2Dependency, dependencyQueue, dependencyPath);
        }

        // 生成每个打包配置对应的assets列表
        var pack2Assets = new Dictionary<string, List<string>>();
        foreach (var item in asset2Pack)
        {
            AddToMap(pack2Assets, item.Value, item.Key);
        }
        var dependency = new List<string>();
        foreach(var item in asset2Dependency)
        {
            if (item.Key.ToLower().EndsWith(".cs"))
                continue;

            if (item.Value > 1)
            {
                dependency.Add(item.Key);
            }
        }
        
        Build(pack2Assets, dependency, encryptLua);
    }

    public void AddDep(Dictionary<string,string> assetDic, Dictionary<string, int> dependencyDic, Queue<string> dependencyQueue, string assetPath)
    {
        var deps = AssetDatabase.GetDependencies(assetPath, false);
        foreach (var dep in deps)
        {
            if (string.Equals(assetPath, dep))
                continue;

            if (assetPath.ToLower().EndsWith(".cs"))
                continue;

            if (!assetDic.ContainsKey(dep) && !dependencyDic.ContainsKey(dep))
            {
                dependencyDic.Add(dep, 1);
                dependencyQueue.Enqueue(dep);
            }
            else if(dependencyDic.ContainsKey(dep))
            {
                dependencyDic[dep]++;
            }
        }
    }
    /// <summary>
    /// 打包指定资源
    /// </summary>
    public void Build(string[] guids, bool encryptLua)
    {
        // 获取所有需要打包的assets
        var assetGuids = new HashSet<string>();
        foreach (var guid in guids)
        {
            
            var path = AssetDatabase.GUIDToAssetPath(guid);
       
            if (Directory.Exists(path))
            {
                var assets = AssetDatabase.FindAssets(string.Empty, new string[] { path });
                foreach (var asset in assets)
                {            
                    assetGuids.Add(asset);
                }
            }
            else
                assetGuids.Add(guid);
        }

        if (assetGuids.Count == 0)
            return;
        
        var pack2Assets = new Dictionary<string, List<string>>();
        foreach (var guid in assetGuids)
        {
            var path = AssetDatabase.GUIDToAssetPath(guid);
            
            var pack = FindAssetPack(path);
            if (!string.IsNullOrEmpty(pack))
                AddToMap(pack2Assets, pack, path);
        }

        var allPack2Assets = new Dictionary<string, List<string>>();
        var newPack2Assets = new Dictionary<string, List<string>>();
        while (pack2Assets.Count > 0)
        {
            foreach (var item in pack2Assets)
            {
                allPack2Assets.Add(item.Key, item.Value);
            }

            // 补全BundleTogether中的所有assets
            foreach (var item in pack2Assets)
            {
                var path = item.Key;
                if (Directory.Exists(path))
                {
                    var guid = AssetDatabase.AssetPathToGUID(path);
                    var pack = GetFloderPack(guid);
                    if (pack.onlyPackerUsed)
                        continue;
                    if (pack.type == FloderPackType.BundleTogether)
                    {
                        item.Value.Clear();
                        item.Value.AddRange(FindAssets(path, pack));
                    }
                }
            }

            // 计算由于依赖产生的新的asset
            foreach (var item in pack2Assets)
            {
                if (!IsBundlePack(item.Key))
                    continue;
                foreach (var assetPath in item.Value)
                {
                    var deps = AssetDatabase.GetDependencies(assetPath);
                    foreach (var dep in deps)
                    {
                     //   UnityEngine.Debug.LogError(dep);
                        if (string.Equals(assetPath, dep))
                            continue;

                        var pack = FindAssetPack(dep);
                        UnityEngine.Debug.Log("IsBundlePackIsBundlePackIsBundlePack" + " " + IsBundlePack(pack) + " " + dep + " " + pack + " " + allPack2Assets.ContainsKey(pack) + " " + newPack2Assets.ContainsKey(pack));
                        var packGuid = AssetDatabase.AssetPathToGUID(pack);
                        var packCfg = GetFloderPack(packGuid);
                        if (IsBundlePack(pack) && !allPack2Assets.ContainsKey(pack) && !newPack2Assets.ContainsKey(pack))
                            AddToMap(newPack2Assets, pack, dep);
                        else
                        {
                            if (packCfg != null && packCfg.onlyPackerUsed)      //只加有依赖的资源
                            {
                                bool needAddDep = true;
                                if (allPack2Assets.ContainsKey(pack))
                                {
                                    foreach (var item1 in allPack2Assets[pack])
                                    {
                                       if((string.Equals(item1, dep)))
                                       { 
                                            needAddDep = false;
                                            break; 
                                        }
                                        UnityEngine.Debug.LogError("item1item1item1item1 " + item1);
                                    }
                                }
                                if (newPack2Assets.ContainsKey(pack))
                                {
                                    foreach (var item2 in newPack2Assets[pack])
                                    {
                                        if ((string.Equals(item2, dep)))
                                        {
                                            needAddDep = false;
                                            break;
                                        }
                                        UnityEngine.Debug.LogError("item2item2item2item2 " + item2);
                                    }
                                }
                                if(needAddDep)
                                    AddToMap(newPack2Assets, pack, dep);
                            }
                        }

                    }
                }
            }

            Swap(ref pack2Assets, ref newPack2Assets);
            newPack2Assets.Clear();
        }

        //Build(allPack2Assets, encryptLua);
    }

    void Build(Dictionary<string, List<string>> pack2Assets, List<string> dependency, bool encryptLua)
    {
        // 需要拷贝的Asset
        List<string> copys = new List<string>();
        // 需要打包成AssetBundle
        List<AssetBundleBuild> builds = new List<AssetBundleBuild>();
        foreach (var item in pack2Assets)
        {
            var guid = AssetDatabase.AssetPathToGUID(item.Key);
            if (Directory.Exists(item.Key))
            {
                var type = GetFloderPackType(AssetDatabase.AssetPathToGUID(item.Key));

                switch (type)
                {
                    case FloderPackType.Copy:
                        copys.AddRange(item.Value);
                        break;
                    case FloderPackType.BundleTogether:
                        {
                            var build = new AssetBundleBuild();
                            build.assetBundleName = GetBundleName(item.Key);
                            build.assetBundleVariant = "unity3d";
                            build.assetNames = item.Value.ToArray();
                            builds.Add(build);
                        }
                        break;
                    case FloderPackType.BundleEachFile:
                        {
                            for (int i = 0; i < item.Value.Count; ++i)
                            {

                                var assetPath = item.Value[i];

                                if (!File.Exists(assetPath))
                                    continue;
                                var build = new AssetBundleBuild();
                                build.assetBundleName = GetBundleName(assetPath);
                                build.assetBundleVariant = "unity3d";
                                build.assetNames = new string[] { assetPath };
                                builds.Add(build);
                            }
                        }
                        break;
                }
            }
            else
            {
                var type = GetFilePackType(AssetDatabase.AssetPathToGUID(item.Key));
                switch (type)
                {
                    case FilePackType.Copy:
                        copys.AddRange(item.Value);
                        break;
                    case FilePackType.Bundle:
                        {
                            for (int i = 0; i < item.Value.Count; ++i)
                            {
                                var assetPath = item.Value[i];
                                var build = new AssetBundleBuild();
                                build.assetBundleName = GetBundleName(assetPath);
                                build.assetBundleVariant = "unity3d";
                                build.assetNames = new string[] { assetPath };
                                builds.Add(build);
                            }
                        }
                        break;
                }
            }
        }

        foreach (var assetPath in dependency)
        {
            if (!assetPath.StartsWith(rootPath)) continue;
            var build = new AssetBundleBuild();
            build.assetBundleName = GetBundleName(assetPath);
            build.assetBundleVariant = "unity3d";
            build.assetNames = new string[] { assetPath };
            builds.Add(build);
        }

        // 拷贝文件
        for (int i = 0; i < copys.Count; ++i)
        {
            var file = copys[i];
            if (file.EndsWith(".lua"))
            {
                var subPath = file.Substring(rootPath.Length + 4);
                EditorUtility.DisplayProgressBar("Copy Files", string.Format("Copy {0}", subPath), (float)(i + 1) / copys.Count);
#if UNITY_ANDROID
                CopyFile(file, outputPath + "/Lua" + subPath, false, false); //现在的MacOS 10.15没办法运行32位程序，没办法制作32位luac，所以先使用原版lua当做32位lua代码
                CopyFile(file, outputPath + "/Lua64" + subPath, encryptLua, true);
#elif UNITY_IOS
                CopyFile(file, outputPath + "/Lua" + subPath, encryptLua, true);
#endif
            }
            else
            {
                var subPath = file.Substring(rootPath.Length);
                EditorUtility.DisplayProgressBar("Copy Files", string.Format("Copy {0}", subPath), (float)(i + 1) / copys.Count);
                CopyFile(file, outputPath + subPath, encryptLua);
            }
        }
        EditorUtility.ClearProgressBar();

        // 打包
        if (builds.Count > 0)
        {
            EditorUtility.DisplayProgressBar("Preparing Build", "", 1);
            var bundlePath = outputPath;
            if (!Directory.Exists(bundlePath))
                Directory.CreateDirectory(bundlePath);
            BuildPipeline.BuildAssetBundles(bundlePath, builds.ToArray(), BuildAssetBundleOptions.ChunkBasedCompression, EditorUserBuildSettings.activeBuildTarget);
            EditorUtility.ClearProgressBar();
        }

        AssetDatabase.Refresh();
    }

    public void CopyLua(bool encryptLua)
    {
        var asset2Pack = new Dictionary<string, string>();

        // 在需要打包的文件夹中搜索Asset
        foreach (var item in floderPacks)
        {
            if (item.type == FloderPackType.None)
                continue;

            var path = AssetDatabase.GUIDToAssetPath(item.guid);
            var assetPathes = FindAssets(path, item);
            foreach (var assetPath in assetPathes)
            {
                string path2;
                if (asset2Pack.TryGetValue(assetPath, out path2))
                {
                    // 该asset的打包配置已经存在，优先使用子目录的打包配置
                    if (path.Length > path2.Length)
                        asset2Pack[assetPath] = path;
                }
                else
                    asset2Pack.Add(assetPath, path);
            }
        }

        // 遍历需要打包的文件
        foreach (var item in filePacks)
        {
            if (item.type == FilePackType.UseFloderPack)
                continue;

            var assetPath = AssetDatabase.GUIDToAssetPath(item.guid);
            if (item.type == FilePackType.None)
            {
                asset2Pack.Remove(assetPath);
                continue;
            }

            asset2Pack[assetPath] = assetPath;
        }

        // 生成每个打包配置对应的assets列表
        var pack2Assets = new Dictionary<string, List<string>>();
        foreach (var item in asset2Pack)
        {
            AddToMap(pack2Assets, item.Value, item.Key);
        }

        // 需要拷贝的Asset
        List<string> copys = new List<string>();
        foreach (var item in pack2Assets)
        {
            var guid = AssetDatabase.AssetPathToGUID(item.Key);
            if (Directory.Exists(item.Key))
            {
                var type = GetFloderPackType(AssetDatabase.AssetPathToGUID(item.Key));
                switch (type)
                {
                    case FloderPackType.Copy:
                        copys.AddRange(item.Value);
                        break;
                }
            }
            else
            {
                var type = GetFilePackType(AssetDatabase.AssetPathToGUID(item.Key));
                switch (type)
                {
                    case FilePackType.Copy:
                        copys.AddRange(item.Value);
                        break;
                }
            }
        }

        // 拷贝文件
        for (int i = 0; i < copys.Count; ++i)
        {
            var file = copys[i];
            if (file.EndsWith(".lua"))
            {
                var subPath = file.Substring(rootPath.Length + 4);
                EditorUtility.DisplayProgressBar("Copy Files", string.Format("Copy {0}", subPath), (float)(i + 1) / copys.Count);

#if UNITY_ANDROID


                // CopyFile(file, outputPath + "/Lua" + subPath, false, false); //现在的MacOS 10.15没办法运行32位程序，没办法制作32位luac，所以先使用原版lua当做32位lua代码
                CopyFile(file, outputPath + "/Lua64" + subPath, encryptLua, true);
#elif UNITY_IOS
                var dir = Path.GetDirectoryName(outputPath + "/lua64");       //ios没有64建一个空目录
                if (!Directory.Exists(dir))
                    Directory.CreateDirectory(dir);
                CopyFile(file, outputPath + "/Lua" + subPath, encryptLua, true);
#endif
            }
            else
            {
                var subPath = file.Substring(rootPath.Length);
                EditorUtility.DisplayProgressBar("Copy Files", string.Format("Copy {0}", subPath), (float)(i + 1) / copys.Count);
                CopyFile(file, outputPath + subPath, encryptLua);
            }
        }
        EditorUtility.ClearProgressBar();

        AssetDatabase.Refresh();
    }

    bool CheckExtenstion(string assetPath, string extension)
    {
        if (string.IsNullOrEmpty(extension))
            return true;

        if (extension.Contains(";") || extension.Contains(" "))
        {
            var extensions = extension.Split("; ".ToCharArray());
            foreach (var e in extensions)
            {
                if (assetPath.EndsWith(e))
                    return true;
            }
            return false;
        }
        else
            return assetPath.EndsWith(extension);
    }

    bool CheckFilter(string assetPath, string filter)
    {
        if (string.IsNullOrEmpty(filter))
            return true;

        var floder = Path.GetDirectoryName(assetPath);
        var findAssets = AssetDatabase.FindAssets(filter, new string[] { floder });
        return ArrayUtil.Contains(findAssets, AssetDatabase.AssetPathToGUID(assetPath));
    }

    string GetBundleName(string path)
    {
        int start = rootPath.Length + 1;
        return path.Substring(start);
    }

    void CopyFile(string srcFile, string destFile, bool encryptLua,bool lua64 = false)
    {
        destFile = destFile.ToLower();
        if (!File.Exists(srcFile))
            return;

        var dir = Path.GetDirectoryName(destFile);
        if (!Directory.Exists(dir))
            Directory.CreateDirectory(dir);

        if (File.Exists(destFile))
            File.Delete(destFile);

        if (encryptLua && srcFile.EndsWith(".lua"))
        {
            if (lua64)
                EncodeLuaFileWin64(srcFile, destFile);
            else
                EncodeLuaFile(srcFile, destFile);
        }
        else
            File.Copy(srcFile, destFile);
    }

    static string AppDataPath
    {
        get { return Application.dataPath.ToLower(); }
    }

    public static void EncodeLuaFileWin64(string srcFile, string outFile)
    {
        //    UnityEngine.Debug.Log(srcFile + " " + outFile);
        if (!srcFile.ToLower().EndsWith(".lua"))
        {
            File.Copy(srcFile, outFile, true);
            return;
        }
        bool isWin = true;
        string luaexe = string.Empty;
        string args = string.Empty;
        string exedir = string.Empty;
        string currDir = Directory.GetCurrentDirectory();
        string workDir = Path.GetDirectoryName(Application.dataPath) + "/";

        if (Application.platform == RuntimePlatform.WindowsEditor)
        {
            luaexe = "luajit64.exe";
            args = "-b -g " + string.Format("{0}{1} {2}", workDir, srcFile, outFile);
            exedir = Path.Combine(new DirectoryInfo(workDir).FullName, "Luajit64/");
        }
        else if (Application.platform == RuntimePlatform.OSXEditor)
        {
            isWin = false;
            luaexe = "luajit";
            args = "-b -g " + string.Format("'{0}{1}' '{2}'", workDir, srcFile, outFile);
            var exePath = "luajit_mac/";
            exedir = Path.Combine(new DirectoryInfo(workDir).FullName, "LuaEncoder/" + exePath);
        }

        Directory.SetCurrentDirectory(exedir);
        //UnityEngine.Debug.LogError("64 " + exedir + luaexe + " " + args);
        ProcessStartInfo info = new ProcessStartInfo(Path.Combine(exedir, luaexe), args);
        info.WindowStyle = ProcessWindowStyle.Hidden;
        info.UseShellExecute = isWin;
        info.ErrorDialog = true;

        Process pro = Process.Start(info);
        pro.WaitForExit();
        pro.Close();
        Directory.SetCurrentDirectory(currDir);

    }
    public static void EncodeLuaFile(string srcFile, string outFile)
    {
        if (!srcFile.ToLower().EndsWith(".lua"))
        {
            File.Copy(srcFile, outFile, true);
            return;
        }
        bool isWin = true;
        string luaexe = string.Empty;
        string args = string.Empty;
        string exedir = string.Empty;
        string currDir = Directory.GetCurrentDirectory();
        string workDir = Path.GetDirectoryName(Application.dataPath) + "/";

        if (Application.platform == RuntimePlatform.WindowsEditor)
        {
            isWin = true;
            luaexe = "luajit32.exe";
            args = "-b -g " + string.Format("{0}{1} {2}", workDir, srcFile, outFile);
            exedir = Path.Combine(new DirectoryInfo(workDir).FullName, "Luajit/");
        }
        else if (Application.platform == RuntimePlatform.OSXEditor)
        {
            isWin = false;
            luaexe = "luajit";
            args = "-b -g " + string.Format("'{0}{1}' '{2}'", workDir, srcFile, outFile);
            var exePath = "luajit_mac_android/";
            exedir =Path.Combine(new DirectoryInfo(workDir).FullName, "LuaEncoder/" + exePath);
        }

        Directory.SetCurrentDirectory(exedir);
        UnityEngine.Debug.LogError("32 " + exedir + luaexe + " " + args);
        ProcessStartInfo info = new ProcessStartInfo(Path.Combine(exedir, luaexe),args);
        info.WindowStyle = ProcessWindowStyle.Hidden;
        info.UseShellExecute = isWin;
        info.ErrorDialog = true;

        Process pro = Process.Start(info);
        pro.WaitForExit();
        pro.Close();
        Directory.SetCurrentDirectory(currDir);
    }

    void Swap<T>(ref T item1, ref T item2)
    {
        var temp = item1;
        item1 = item2;
        item2 = temp;
    }

    void AddToMap(Dictionary<string, List<string>> map, string key, string item)
    {
        List<string> list;
        if (!map.TryGetValue(key, out list))
        {
            list = new List<string>();
            map.Add(key, list);
        }
        list.Add(item);
    }

    // 获取asset的打包配置
    string FindAssetPack(string assetPath)
    {
        var guid = AssetDatabase.AssetPathToGUID(assetPath);
        var filePackType = GetFilePackType(guid);
        if (filePackType == FilePackType.None)
            return string.Empty;

        if (filePackType != FilePackType.UseFloderPack)
            return assetPath.Replace('\\', '/');

        var path = assetPath;
        while (true)
        {
            path = Path.GetDirectoryName(path);
            if (path.Length <= rootPath.Length)
                return string.Empty;

            guid = AssetDatabase.AssetPathToGUID(path);
            var pack = GetFloderPack(guid);
            if (pack == null || pack.type == FloderPackType.None)
                continue;
            if (!CheckExtenstion(assetPath, pack.extension))
                continue;

            if (!CheckFilter(assetPath, pack.filter))
                continue;

            return path.Replace('\\', '/');
        }
    }

    List<string> FindAssets(string path, FloderPack pack)
    {
        var assets = new List<string>();
        var guids = AssetDatabase.FindAssets(pack.filter, new string[] { path });
      
        foreach (var guid in guids)
        {
            var assetPath = AssetDatabase.GUIDToAssetPath(guid);
            if (assets.Contains(assetPath))
                continue;

            if (!CheckExtenstion(assetPath, pack.extension))
                continue;
           // UnityEngine.Debug.Log(FindAssetPack(assetPath) + " " + assetPath + " " + path + " guidsguidsguidsguids");
            if (string.Equals(FindAssetPack(assetPath), path))
                assets.Add(assetPath);
        }
        return assets;
    }

    bool IsBundlePack(string path)
    {
        var guid = AssetDatabase.AssetPathToGUID(path);
        if (Directory.Exists(path))
        {
            var floderType = GetFloderPackType(guid);
            return floderType == FloderPackType.BundleEachFile || floderType == FloderPackType.BundleTogether;
        }
        else
        {
            var fileType = GetFilePackType(guid);
            return fileType == FilePackType.Bundle;
        }
    }

    #endregion
}